<?php

namespace common\components;

use backend\Backend;
use Closure;
use common\widgets\grid\BulkAjaxActionBtn;
use common\widgets\pages\AdminPage;
use common\widgets\pages\FormViewPage;
use common\widgets\pages\GridViewPage;
use Yii;
use yii\helpers\ArrayHelper;
use yii\helpers\Url;
use yii\web\Controller as WebController;
use yii\web\HttpException;
use yii\web\Response;

/**
 * 基础控制器组件
 *
 * @package common\components
 */
class Controller extends WebController
{

    /**
     * {@inheritdoc}
     */
    public $enableCsrfValidation = false;

    /**
     * {@inheritdoc}
     */
    public $rootActions = [];

    /**
     * @var null
     */
    public $error = null;

    /**
     * Write in sessions alert messages
     *
     * @param string $type    error or success
     * @param string $message alert body
     * @param null   $url
     * @return string
     */
    public function flash($type, $message, $url = null)
    {
        Yii::$app->getSession()->setFlash($type == 'error' ? 'danger' : $type, $message);

        if ($url !== null)
        {
            $this->redirect($url);
        }
        return '';
    }

    /**
     * 跳转会上一页
     *
     * @return Response
     */
    public function back()
    {
        return $this->redirect(Yii::$app->request->referrer);
    }

    /**
     * Set return url for module in sessions
     *
     * @param mixed $url if not set, returnUrl will be current page
     */
    public function setReturnUrl($url = null)
    {
        Yii::$app->getSession()->set($this->module->id . '_return', $url ? Url::to($url) : Url::current());
    }

    /**
     * Get return url for module from session
     *
     * @param mixed $defaultUrl if return url not found in sessions
     * @return mixed
     */
    public function getReturnUrl($defaultUrl = null)
    {
        return Yii::$app->getSession()->get($this->module->id . '_return', $defaultUrl
            ? Url::to($defaultUrl)
            : Url::to(Backend::url($this->module->id)));
    }

    /**
     * 根据请求类型来决定返回数据（是否是ajax）
     *
     * @param string $success
     * @param bool   $back go back or refresh
     * @return mixed $result array if request is ajax.
     */
    public function formatResponse($success = '', $back = true)
    {
        if (Yii::$app->request->isAjax)
        {
            Yii::$app->response->format = Response::FORMAT_JSON;
            if ($this->error)
            {
                return ['result' => 'error', 'error' => $this->error];
            }
            else
            {
                $response = ['result' => 'success'];
                if ($success)
                {
                    if (is_array($success))
                    {
                        $response = array_merge(['result' => 'success'], $success);
                    }
                    else
                    {
                        $response = array_merge(['result' => 'success'], ['message' => $success]);
                    }
                }
                return $response;
            }
        }
        else
        {
            if ($this->error)
            {
                $this->flash('error', $this->error);
            }
            else
            {
                if (is_array($success) && isset($success['message']))
                {
                    $this->flash('success', $success['message']);
                }
                elseif (is_string($success))
                {
                    $this->flash('success', $success);
                }
            }
            return $back ? $this->back() : $this->refresh();
        }
    }

    public function ajaxBlukAction(Closure $handler)
    {
        if (Yii::$app->getRequest()->validateCsrfToken() && Yii::$app->getRequest()->isAjax)
        {
            if (($ids = Yii::$app->request->post('keys')) !== null)
            {
                $result = $handler($ids);
                if (is_array($result))
                {
                    return BulkAjaxActionBtn::ajaxReturnSuccess($result['msg'], $result['code'], $result['data']);
                }
                else
                {
                    return BulkAjaxActionBtn::ajaxReturnSuccess($result);
                }
            }
            else
            {
                throw new HttpException(400, "Illegal request.");
            }
        }
        else
        {
            return BulkAjaxActionBtn::ajaxReturnError("Illegal request or data.");
        }
    }

    /**
     * @param string $className
     * @param array  $params
     * @return  AdminPage
     */
    public function createPageInstance($className, $params = [])
    {
        if ( ! isset($params[AdminPage::CONTROLLER]))
        {
            $params[AdminPage::CONTROLLER] = $this;
        }

        return new $className($params);
    }

    /**
     * @param       $provider
     * @param       $searchModel
     * @param array $params
     * @return \common\widgets\pages\GridViewPage
     */
    public function createGridViewPage($provider, $searchModel, $params = [])
    {
        $params = ArrayHelper::merge([
            GridViewPage::DATA_PROVIDER => $provider,
            GridViewPage::SEARCH_MODEL  => $searchModel,
        ], $params);

        return $this->createPageInstance(GridViewPage::className(), $params);
    }

    /**
     * @param       $formModel
     * @param       $method
     * @param array $params
     * @return \common\widgets\pages\GridViewPage
     */
    public function createFormViewPage($formModel, $method, $params = [])
    {
        $params = ArrayHelper::merge([
            'formModel' => $formModel,
            'method'    => $method,
        ], $params);

        return $this->createPageInstance(FormViewPage::className(), $params);
    }
}
